core: canonicalize bare-user xattrs
authorColin Walters <walters@verbum.org>
Tue, 25 Feb 2025 19:14:19 +0000 (14:14 -0500)
committerColin Walters <walters@verbum.org>
Tue, 25 Feb 2025 19:58:35 +0000 (14:58 -0500)
Previously we were erroring out if xattrs were provided in
non-canonical (e.g. unsorted) form all the way down to just
the bare-user path. But for archive repos and dirmeta we
canonicalized.

Canonicalize bare-user xattrs on both read and write consistently
instead of erroring.

Signed-off-by: Colin Walters <walters@verbum.org>
src/libostree/ostree-core-private.h
src/libostree/ostree-core.c
src/libostree/ostree-repo-commit.c
src/libostree/ostree-repo.c

index 283944b4a9a3b8ddd50e147e0f0fa71ae3ae3221..2996e11a554cb0f2c24785228eec6a0dc7b52f0b 100644 (file)
@@ -90,6 +90,7 @@ void _ostree_gfileinfo_to_stbuf (GFileInfo *file_info, struct stat *out_stbuf);
 gboolean _ostree_gfileinfo_equal (GFileInfo *a, GFileInfo *b);
 gboolean _ostree_stbuf_equal (struct stat *stbuf_a, struct stat *stbuf_b);
 GFileInfo *_ostree_mode_uidgid_to_gfileinfo (mode_t mode, uid_t uid, gid_t gid);
+GVariant *_ostree_canonicalize_xattrs (GVariant *xattrs);
 gboolean _ostree_validate_structureof_xattrs (GVariant *xattrs, GError **error);
 
 static inline void
index 4a9d68daa5670806458e51fcf09aab1567fa0022..3e462838f60384b68fc90f2a8a7e0d2dc6b53d97 100644 (file)
@@ -43,7 +43,6 @@ G_STATIC_ASSERT (OSTREE_REPO_MODE_BARE_USER_ONLY == 3);
 G_STATIC_ASSERT (OSTREE_REPO_MODE_BARE_SPLIT_XATTRS == 4);
 
 static GBytes *variant_to_lenprefixed_buffer (GVariant *variant);
-static GVariant *canonicalize_xattrs (GVariant *xattrs);
 
 #define ALIGN_VALUE(this, boundary) \
   ((((unsigned long)(this)) + (((unsigned long)(boundary)) - 1)) \
@@ -317,8 +316,8 @@ compare_xattrs (const void *a_pp, const void *b_pp)
 }
 
 // Sort xattrs by name
-static GVariant *
-canonicalize_xattrs (GVariant *xattrs)
+GVariant *
+_ostree_canonicalize_xattrs (GVariant *xattrs)
 {
   // We always need to provide data, so NULL is canonicalized to the empty array
   if (xattrs == NULL)
@@ -364,7 +363,7 @@ _ostree_file_header_new (GFileInfo *file_info, GVariant *xattrs)
     symlink_target = "";
 
   // We always sort the xattrs now to ensure everything is in normal/canonical form.
-  g_autoptr (GVariant) tmp_xattrs = canonicalize_xattrs (xattrs);
+  g_autoptr (GVariant) tmp_xattrs = _ostree_canonicalize_xattrs (xattrs);
 
   g_autoptr (GVariant) ret
       = g_variant_new ("(uuuus@a(ayay))", GUINT32_TO_BE (uid), GUINT32_TO_BE (gid),
@@ -1153,7 +1152,7 @@ ostree_create_directory_metadata (GFileInfo *dir_info, GVariant *xattrs)
   GVariant *ret_metadata = NULL;
 
   // We always sort the xattrs now to ensure everything is in normal/canonical form.
-  g_autoptr (GVariant) tmp_xattrs = canonicalize_xattrs (xattrs);
+  g_autoptr (GVariant) tmp_xattrs = _ostree_canonicalize_xattrs (xattrs);
 
   ret_metadata = g_variant_new (
       "(uuu@a(ayay))", GUINT32_TO_BE (g_file_info_get_attribute_uint32 (dir_info, "unix::uid")),
index 5c5ac729f2cdcbe332a320e5c3087d21ec398dd0..c5a47d32c833f5e1f3fccb6d0e5344bbd75a6de4 100644 (file)
@@ -140,9 +140,11 @@ _ostree_write_bareuser_metadata (int fd, guint32 uid, guint32 gid, guint32 mode,
                                  GError **error)
 {
   GLNX_AUTO_PREFIX_ERROR ("Writing bareuser metadata", error);
-  if (xattrs != NULL && !_ostree_validate_structureof_xattrs (xattrs, error))
-    return FALSE;
-  g_autoptr (GVariant) filemeta = create_file_metadata (uid, gid, mode, xattrs);
+  // Like we do elsewhere, ensure xattrs are in canonical form. We don't strictly need
+  // this because we don't actually provide this data directly as input to a checksum today,
+  // but it's good hygeine to do so.
+  g_autoptr (GVariant) tmp_xattrs = _ostree_canonicalize_xattrs (xattrs);
+  g_autoptr (GVariant) filemeta = create_file_metadata (uid, gid, mode, tmp_xattrs);
 
   if (TEMP_FAILURE_RETRY (fsetxattr (fd, "user.ostreemeta", (char *)g_variant_get_data (filemeta),
                                      g_variant_get_size (filemeta), 0))
index 2f4e836c6559a08943ffa13f5b6113f063bca31a..4e2f47d0e73aa5f38ffab79eeb112028c7c14c30 100644 (file)
@@ -4098,7 +4098,10 @@ _ostree_repo_load_file_bare (OstreeRepo *self, const char *checksum, int *out_fd
 
       g_autoptr (GVariant) metadata = g_variant_ref_sink (
           g_variant_new_from_bytes (OSTREE_FILEMETA_GVARIANT_FORMAT, bytes, FALSE));
-      ret_xattrs = filemeta_to_stat (&stbuf, metadata);
+      g_autoptr (GVariant) read_xattrs = filemeta_to_stat (&stbuf, metadata);
+      // Old versions of ostree may have written these xattrs in non-canonical form.
+      // In order to aid comparisons, let's canonicalize here.
+      ret_xattrs = _ostree_canonicalize_xattrs (read_xattrs);
       if (S_ISLNK (stbuf.st_mode))
         {
           if (out_symlink)